package com.tlgen.modules.common.service.impl;

import com.tlgen.common.exception.BadRequestException;
import com.tlgen.common.exception.EntityExistException;
import com.tlgen.common.utils.FileUtil;
import com.tlgen.common.utils.QueryHelp;
import com.tlgen.common.utils.ValidationUtil;
import com.tlgen.modules.common.domain.J_Area;
import com.tlgen.modules.common.repository.J_AreaRepository;
import com.tlgen.modules.common.service.J_AreaService;
import com.tlgen.modules.common.service.dto.J_AreaDto;
import com.tlgen.modules.common.service.dto.J_AreaQueryCriteria;
import com.tlgen.modules.common.service.mapper.J_AreaMapper;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**功能描述：乡镇村
 */
@Service
@CacheConfig(cacheNames = "j_Area")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class J_AreaServiceImpl implements J_AreaService {

    private final J_AreaRepository j_areaRepository;

    private final J_AreaMapper j_areaMapper;

    public J_AreaServiceImpl(J_AreaRepository j_areaRepository, J_AreaMapper j_areaMapper) {
        this.j_areaRepository = j_areaRepository;
        this.j_areaMapper = j_areaMapper;
    }

    @Override
    public Map<String, Object> buildTree(List<J_AreaDto> j_areaDtos) {
        List<J_AreaDto> trees = new ArrayList<>();
        Set<Long> ids = new HashSet<>();
        for (J_AreaDto j_areaDTO : j_areaDtos) {
            if (j_areaDTO.getPid() == 0) {
                trees.add(j_areaDTO);
            }
            for (J_AreaDto it : j_areaDtos) {
                if (it.getPid().equals(j_areaDTO.getId())) {
                    if (j_areaDTO.getChildren() == null) {
                        j_areaDTO.setChildren(new ArrayList<>());
                    }
                    j_areaDTO.getChildren().add(it);
                    ids.add(it.getId());
                }
            }
        }
        Map<String, Object> map = new HashMap<>(2);
        if (trees.size() == 0) {
            trees = j_areaDtos.stream().filter(s -> !ids.contains(s.getId())).collect(Collectors.toList());
        }
        map.put("content", trees);
        map.put("totalElements", j_areaDtos.size());
        return map;
    }

    @Override
    public List<J_AreaDto> buildJ_Areas(List<J_AreaDto> j_areaDtos) {
        List<J_AreaDto> list = new LinkedList<>();
        j_areaDtos.forEach(j_areaDTO -> {
            List<J_AreaDto> jAreaDtoList = new LinkedList<>();
            J_AreaDto j_areaDto = new J_AreaDto();
            j_areaDto.setChildren(buildJ_Areas(jAreaDtoList));
            list.add(j_areaDto);

        });
        return list;
    }

    @Override
    public List<J_AreaDto> queryAll(J_AreaQueryCriteria criteria) {
        return j_areaMapper.toDto(j_areaRepository.findAll(((root, criteriaQuery, criteriaBuilder) ->
                QueryHelp.getPredicate(root, criteria, criteriaBuilder))));
    }

    @Override
    @Cacheable(key = "'pid:'+#p0")
    public List<J_Area> findByPid(long pid) {
        return j_areaRepository.findByPid(pid);
    }

    @Override
    @Cacheable(key = "'tree'")
    public Object getJ_AreaTree(List<J_Area> j_areas) {
        List<Map<String, Object>> list = new LinkedList<>();
        j_areas.forEach(j_area -> {
            if (j_area != null) {
                List<J_Area> j_areaList = j_areaRepository.findByPid(j_area.getId());
                Map<String, Object> map = new HashMap<>(16);
                map.put("id", j_area.getId());
                map.put("label", j_area.getCounty());
                if (j_areaList != null && j_areaList.size() != 0) {
                    map.put("children", getJ_AreaTree(j_areaList));
                }
                list.add(map);
            }
        });
        return list;
    }

    @Override
    @CacheEvict(allEntries = true)
    public J_AreaDto create(J_Area resources) {
        return j_areaMapper.toDto(j_areaRepository.save(resources));
    }

    @Override
    @CacheEvict(allEntries = true)
    public void update(J_Area resources) {
        if (resources.getId().equals(resources.getPid())) {
            throw new BadRequestException("上级不能为自己!");
        }
        J_Area j_area = j_areaRepository.findById(resources.getId()).orElseGet(J_Area::new);
        ValidationUtil.isNull(j_area.getId(), "id", "id", resources.getId());

        J_Area j_area1 = j_areaRepository.findByCounty(resources.getCounty());
        if (j_area1 != null && !j_area1.getId().equals(j_area.getId())) {
            throw new EntityExistException(J_Area.class, "county", resources.getCounty());
        }
        j_area.setCounty(resources.getCounty());
        j_area.setCode(resources.getCode());
        j_area.setPid(resources.getPid());
        j_areaRepository.save(j_area);
    }

    @Override
    public Set<J_Area> getDeleteJ_Areas(List<J_Area> j_areaList, Set<J_Area> j_areaSet) {
        for (J_Area j_area : j_areaList) {
            j_areaSet.add(j_area);
            List<J_Area> j_areas = j_areaRepository.findByPid(j_area.getId());
            if (j_areas != null && j_areas.size() !=0) {
                getDeleteJ_Areas(j_areas, j_areaSet);
            }
        }
        return j_areaSet;
    }

    @Override
    public J_Area findOne(Long id) {
        J_Area j_area = j_areaRepository.findById(id).orElseGet(J_Area::new);
        ValidationUtil.isNull(j_area.getId(), "J_Area", "id", id);
        return j_area;
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public void delete(Set<J_Area> j_areaSet) {
        for (J_Area j_area : j_areaSet) {
            j_areaRepository.deleteById(j_area.getId());
        }
    }

    @Override
    public void download(List<J_AreaDto> queryAll, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (J_AreaDto j_areaDto : queryAll) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("行政区域名称", j_areaDto.getCounty());
            map.put("行政区域编码", j_areaDto.getCode());
            map.put("父id", j_areaDto.getPid());
            map.put("子行政区域", j_areaDto.getChildren());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

}
